﻿using System;
using System.Linq;
using System.Collections.Generic;

using Microsoft.Xna.Framework;

using Ah.Testudin.Engine.Graphics;
using Ah.Testudin.Engine.UI.Elements;
using Ah.Testudin.Engine.Input;

namespace Ah.Testudin.Engine.UI.Views
{
    public abstract class HumanViewBase : IGameView
    {
        #region Private Member Variables

        private IList<IScreenElement> _screenElements;

        private readonly ITestudinRenderer _renderer;

        private readonly ICursor _cursor;

        #endregion

        #region Constructors

        public HumanViewBase(
            IList<IScreenElement> screenElements,
            ICursor cursor)
        {
            if (screenElements == null)
            {
                screenElements = new List<IScreenElement>();
            }

            if (cursor == null)
            {
                throw new ArgumentNullException("cursor");
            }

            _screenElements = screenElements;

            _cursor = cursor;

            _renderer = GraphicsDeviceRendererSingleton.Instance;
        }

        #endregion

        #region IGameView

        public virtual bool ProcessInput()
        {
            foreach (IScreenElement currentScreenElement in _screenElements.OrderBy(x => x.ZOrder).Reverse())
            {
                if (currentScreenElement.ProcessInput())
                {
                    return true;
                }
            }

            return false;
        }

        public virtual void Update(GameTime gameTime)
        {
            _cursor.Update();

            foreach (IScreenElement currentScreenElement in
                _screenElements.OrderBy(x => x.ZOrder).Reverse())
            {
                currentScreenElement.Update(gameTime);
            }
        }

        public virtual void Render()
        {
            foreach (IScreenElement currentScreenElement in
                _screenElements.OrderBy(x => x.ZOrder))
            {
                if (currentScreenElement.Visible)
                {
                    currentScreenElement.Render();
                }
            }

            _cursor.Render();
        }

        public void Dispose()
        {
            foreach (IScreenElement currentScreenElement in _screenElements)
            {
                currentScreenElement.Dispose();
            }

            _screenElements.Clear();
        }

        #endregion

        #region Public Methods

        public void AddScreenElement(IScreenElement screenElement)
        {
            if (screenElement == null)
            {
                throw new ArgumentNullException("screenElement");
            }

            _screenElements.Add(screenElement);
        }

        public void RemoveScreenElement(IScreenElement screenElement)
        {
            if (screenElement == null)
            {
                throw new ArgumentNullException("screenElement");
            }

            _screenElements.Remove(screenElement);
        }

        #endregion
    }
}
